home *** CD-ROM | disk | FTP | other *** search
- /*
- ** $VER: graphics3D2d_o.c 10.00 (06.05.98)
- **
- ** Internal functions for graphics3D.library
- ** Optimezed 2D functions
- **
- ** (C) Copyright 98 Patrizio Biancalani
- ** All Rights Reserved.
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <proto/exec.h>
- #include <proto/intuition.h>
- #include <intuition/intuition.h>
- #include <intuition/screens.h>
-
- #include <graphics/rastport.h>
- #include <graphics/clip.h>
- #include <graphics/regions.h>
- #include <graphics/gfx.h>
- #include <graphics/gfxmacros.h>
- #include <graphics/layers.h>
-
- #include "graphics3Dc.h"
- #include "graphics3D.h"
- #include "graphics3D2d_proto.h"
-
- /* Please note, that &Graphics3DBase always resides in register __a6
- as well, but if we don't need it, we need not reference it here.
-
- Also note, that registers a0, a1, d0, d1 always are scratch registers,
- so you usually should only *pass* parameters there, but make a copy
- directly after entering the function. To avoid problems of kind
- "implementation defined behaviour", you should make a copy of A6 too,
- when it is actually used.
-
- In this example case, scratch register saving would not have been
- necessary (since there are no other function calls inbetween), but we
- did it nevertheless.
- */
-
- struct pixl {
- long int x;
- long int y;
- };
-
- /************ prototipi solo locali ******/
- struct RastPort *InitNBuff(struct grafica *graf);
-
- void FreeNBuff(struct grafica *graf);
-
- /**********************************************************/
-
- /************ macro solo locali ******/
- #define DIPIU 500
- #define PREC 8
- /*************************************/
-
- /****************************************************
- ** Routin per la gestione della grafica, in stile **
- ** 2.0 Ottimizzate **
- ** (c) 1994 BIANCA HARD&SOFT Vers:1.00 **
- ****************************************************/
-
- /********* FUNZIONI DI INIZIALIZAZIONE PER IL 2D ********************************/
-
- /***********************************
- ** INIZIALIZZO STRUTTURE PER USO **
- ** CON ROUTIN OTTIMIZZATE. **
- ***********************************
- **** INPUT : **
- ** win -> puntatore a finestra **
- ** su cui lavorare. **
- ** mxv -> n# massimo vertici da **
- ** usare. **
- ** dx -> larghezza box di visual.**
- ** dy -> altezza box di visual. **
- **** OUTPUT : **
- ** ris >0 - tutto ok. **
- ** ris =<0 - errore, ini.fallita.**
- ***********************************/
- struct grafica *ini_g(struct Window *win,long int mxv,long int dx,long int dy)
- {
- struct grafica *ris;
- struct Screen *scr;
- struct RastPort *rw;
- struct RastPort *r;
- long int i;
-
- ris=(struct grafica *)AllocMem(sizeof(Sgrafica),NULL);
- if (ris==NULL) return (0);
-
- ris->vpor=0;
- ris->rast=0;
- ris->rast1=0;
- ris->rast2=0;
- ris->fdouble=1;
- ris->b_af=0;
- ris->pras=0;
-
- /** default si single buffer **/
- ris->clipx=0;
- ris->clipy=0;
- i=((dx+15)/16)*16;
- ris->clipdx=i;
- ris->clipdy=dy;
- ris->dbuf=0;
- ris->ldbuf=0;
- ris->tmp_rp.BitMap=0;
-
- rw=win->RPort;
- scr=win->WScreen;
- ris->vpor=&(scr->ViewPort);
- ris->wind=win;
-
- r=InitNBuff(ris);
- if ((long int)r==NULL) {
- close_g(ris);
- return(0);
- }
- ris->rast1=rw;
- ris->rast2=r;
- ris->rast=r;
-
- return(ris);
- }
-
- /***********************************
- ** CHIUDO TUTTE LE STRUTTURE **
- ** APERTE CON LA FUNZIONE PRECE- **
- ** DENTE. **
- ***********************************
- **** INPUT : **
- ** graf -> valore >0 ritornato **
- ** dalla funzione d'ini- **
- ** zializzazione **
- ***********************************/
- void close_g(struct grafica *graf)
- {
- struct RastPort *r;
- struct Layer *la;
- long int c;
-
- if ((long int)graf != NULL)
- {
- if (graf->dbuf!=NULL) FreeNBuff(graf);
- FreeMem(graf,sizeof(Sgrafica));
- }
- }
-
- /************************************
- ** FUNZIONE PER VISUALIZZARE IL **
- ** DISPLAY BUFFER CHUNKY NELLA **
- ** FINESTRA. **
- ************************************
- **** INPUT : **
- ** graf -> valore >0 ritornato **
- ** dalla funzione d'ini- **
- ** zializzazione. **
- **** OUTPUT: **
- ************************************/
- void switch_rp(graf)
- struct grafica *graf;
- {
- long int x,y;
-
- x=graf->clipx;
- y=graf->clipy;
-
- if (graf) WritePixelArray8(graf->rast,x,y,x+graf->clipdx-1,y+graf->clipdy-1,
- graf->dbuf,&graf->tmp_rp);
-
- }
-
- /************************************
- ** FUNZIONE PER DEFINIRE UN BOX **
- ** DI CLIP SULLA FINESTRA **
- ************************************
- **** INPUT : **
- ** graf -> valore >0 ritornato **
- ** dalla funzione d'ini- **
- ** zializzazione. **
- ** minx - valore minimo x box. **
- ** miny - valore minimo y box. **
- ** dx - larghezza box. **
- ** dy - altezza box. **
- **** OUTPUT: **
- ** > 0 tutto ok, valore effettivo **
- ** larghezza box in pixel. **
- ** = 0 errore. **
- **** NOTA: **
- ** elimina eventuali clip region **
- ** preesistenti. **
- ** Se dx o dy =0 allora ritorna **
- ** valore effettivo di dx. **
- ************************************/
- long int clipbox(struct grafica *graf,long int minx,
- long int miny,long int dx,long int dy)
- {
- struct Layer *la;
- struct Region *clipr;
- struct Rectangle rect;
- struct ClipRect *clrt;
- long int esi;
- long int i;
-
- #ifdef DEBUG
- char dbg[80];
- #endif
-
- if (dx==0 OR dy==0) return(graf->clipdx);
-
- i=((dx+15)/16)*16;
-
- graf->clipx=minx;
- graf->clipy=miny;
-
- /* se uso libreria ottimizzata */
- if (graf->clipdx!=i OR graf->clipdy!=dy)
- {
- graf->clipdx=i;
- graf->clipdy=dy;
- FreeNBuff(graf);
- InitNBuff(graf);
- }
-
- return (graf->clipdx);
- }
-
- /*************************************
- ** FUNZIONE PER CANCELLARE UN BOX **
- ** NELLA FINESTRA . **
- *************************************
- **** INPUT : **
- ** graf -> valore >0 ritornato da **
- ** ini_g(). **
- ** x0 -> coord. x punto in alto **
- ** a sinistra box. **
- ** y0 -> coord. y punto in alto **
- ** a sinistra box. **
- ** x1 -> coord. x punto in basso **
- ** a destra box. **
- ** y1 -> coord. y punto in basso **
- ** a destra box. **
- **** NOTA : **
- ** usa il colore dello sfondo, e **
- ** non influenza le altre funzioni **
- *************************************/
- /*
- void cls_b(struct grafica *graf,long int x0,
- long int y0,long int x1,long int y1)
- {
- long int i;
- char c,*db;
- if (((long int)graf<=NULL) OR ((long int)(graf->rast)<=NULL)) return(0);
- EraseRect(graf->rast,x0,y0,x1,y1);
- }
- */
-
- /*************************************
- ** FUNZIONE PER CAMBIARE IL MODO **
- ** VIDEO DI TRACCIAMENTO. **
- *************************************
- **** INPUT : **
- ** graf -> valore >0 ritornato da **
- ** ini_g(). **
- ** mod -> nuovo modo video. **
- **** NOTA : **
- ** valori per mod : **
- ** 0 > JAM1 (over 2) **
- ** 1 > JAM2 (over 0) (def.) **
- ** 2 > COMPLEMENT (over 1) **
- ** 4 > INVERSVID (inverse 1) **
- *************************************/
- void over(struct grafica *graf,long int mod)
- {
- if (((long int)graf<=NULL) OR ((long int)(graf->rast)<=NULL)) return(0);
-
- SetDrMd(graf->rast,mod);
- }
-
- /********* ROUTIN INTERNE PER PSEUDO DOUBLE BUFFERING ***************/
- /*********************************************
- ** INIZIALIZZO UN DISPLAY BUFFER DI TIPO **
- ** CHUNKY PER USARE POI WritePixelArray8().**
- *********************************************
- **** INPUT : **
- **** OUTPUT: **
- ** se > 0 allora puntatore a nuova rastport**
- *********************************************
- ** nota: la larghezza del box di visualiz. **
- ** deve essere un multiplo di 16. **
- *********************************************/
- struct RastPort *InitNBuff(struct grafica *graf)
- {
- struct RastPort *rport = NULL;
- struct Window *win;
- short int err = NULL;
- char *c;
- unsigned char depth;
- long int i;
-
- win=graf->wind;
-
- graf->tmp_rp.BitMap=NULL;
- graf->dbuf=NULL;
-
- InitRastPort(&graf->tmp_rp);
-
- /**
- Uso le routin ottimizzate definisco un display buffer tipo chunky e una rastport temp.
- per WritePixelArray8().
- Nota :la larghezza del display buffer deve essere multipla di 16 (una word)).
- **/
- rport=win->RPort;
-
- graf->ldbuf=graf->clipdx * graf->clipdy;
- graf->dbuf=(char *)AllocMem(graf->ldbuf+DIPIU,NULL);
- if (graf->dbuf==NULL) {
- err=1;
- goto NBInit_done ;
- }
- graf->tmp_rp.Layer=NULL;
- graf->tmp_rp.BitMap=(struct BitMap *)AllocBitMap(graf->clipdx,1,8, BMF_CLEAR|BMF_DISPLAYABLE,rport->BitMap);
-
- if (graf->tmp_rp.BitMap==NULL) {
- err=2;
- goto NBInit_done ;
- }
-
- /* inizializzo il display buffer con tutti 0 */
- c=graf->dbuf;
- for(i=0 ;i<graf->ldbuf; i++) c[i]=0;
-
- NBInit_done:
- if (err) FreeNBuff(graf);
- return (rport);
- }
-
- /***************************************************
- ** CHIUDO TUTTE LE AREE APERTE DALLA InitNBuff() **
- ***************************************************/
- void FreeNBuff(struct grafica *graf)
- {
-
- if (graf->dbuf) FreeMem(graf->dbuf,graf->ldbuf + DIPIU);
- if (graf->tmp_rp.BitMap)
- {
- WaitBlit();
- FreeBitMap(graf->tmp_rp.BitMap);
- }
-
- }
-
- /********* FUNZIONI GRAFICHE 2D OTTIMIZZATE ********************************/
-
- /***********************************
- ** RIEMPIO IL DISPLAY FILE COL **
- ** COLORE DELLO SFONDO. **
- ***********************************
- **** INPUT : **
- ** amb3d -> valore >0 ritornato **
- ** dalla funzione d'ini- **
- ** zializzazione. **
- **** OUTPUT: **
- ** nessuno . **
- ***********************************/
- void cls_f(amb3d)
- struct ambient3d *amb3d;
- {
- char col,*c;
- long int i;
-
- /* inizializzo il display buffer con gcolor */
- c=amb3d->graf->dbuf;
- col=amb3d->gcolor;
- for(i=0 ;i<amb3d->graf->ldbuf; i++) c[i]=col;
-
- }
-
- /***********************************
- ** DISEGNO UN PIXEL NEL DISPLAY **
- ** BUFFER CHUNKY. **
- ***********************************
- **** INPUT : **
- ** amb3d -> valore >0 ritornato **
- ** dalla funzione d'ini- **
- ** zializzazione. **
- ** x -> coordinata x . **
- ** y -> coordinata y . **
- ** col-> colore pixel. **
- **** OUTPUT: **
- ** nessuno . **
- ***********************************/
- void pixel(amb3d,x,y,col)
- struct ambient3d *amb3d;
- short int x;
- short int y;
- long int col;
- {
- struct grafica *gf;
- short int dx;
- char *db;
-
- gf=amb3d->graf;
- db=gf->dbuf;
- dx=gf->clipdx;
-
- if (x>=NULL AND x<dx AND y>=NULL AND y<gf->clipdy) db[dx*y+x]=(char)col;
-
- }
-
- /***********************************
- ** DISEGNO UNA RIGA NEL DISPLAY **
- ** BUFFER CHUNKY. **
- ***********************************
- **** INPUT : **
- ** amb3d -> valore >0 ritornato **
- ** dalla funzione d'ini- **
- ** zializzazione. **
- ** x -> coordinata x partenza. **
- ** y -> coordinata y partenza. **
- ** x1 -> coordinata x arrivo. **
- ** y1 -> coordinata y arrivo. **
- ** col-> colore riga. **
- **** OUTPUT: **
- ** nessuno . **
- ***********************************/
- void line(amb3d,x,y,x1,y1,col)
- struct ambient3d *amb3d;
- short int x;
- short int y;
- short int x1;
- short int y1;
- long int col;
- {
- struct grafica *gf;
- char *db;
- short int xm,ym,xx;
- long int xs,ys,xe,ye,dx,dy;
- long int xa,ya,xb,yb;
- long int ii,i,a,b;
-
- #ifdef DEBUG
- char dbg[100];
- #endif
-
- gf=amb3d->graf;
- db=gf->dbuf;
- xm=(short int)gf->clipdx;
- ym=(short int)gf->clipdy;
- xx=xm;
-
- if (x==x1 AND y==y1)
- {
- pixel(amb3d,x,y);
- return(0);
- }
-
- xs=(long int)x<<PREC;
- xe=(long int)x1<<PREC;
- ys=(long int)y<<PREC;
- ye=(long int)y1<<PREC;
-
- dy=ye-ys;
- dx=xe-xs;
- if (dy<NULL) dy=-dy;
- if (dx<NULL) dx=-dx;
- if (dy<dx)
- {
- dy=dy/(dx>>PREC);
- if (ys>ye) dy=-dy;
- a=ys;
- xa=xs>>PREC;
- xb=xe>>PREC;
- ii=1;
- if (xs>xe) ii=-1;
- for(b=xa ;b!=xb ;b=b+ii)
- {
- i=a>>PREC;
- if (b>=0 AND b<xm AND i>=0 AND i<ym) db[i*xx+b]=(char)col;
- a=a+dy;
- }
- }
- else
- {
- dx=dx/(dy>>PREC);
- if (xs>xe) dx=-dx;
- a=xs;
- ya=ys>>PREC;
- yb=ye>>PREC;
- ii=1;
- if (ys>ye) ii=-1;
- for(b=ya ;b!=yb ;b=b+ii)
- {
- i=a>>PREC;
- if (b>=0 AND b<ym AND i>=0 AND i<xm) db[b*xx+i]=(char)col;
- a=a+dx;
- }
- }
- }
-
- /***********************************
- ** DISEGNO UN TRIANGOLO CON O **
- ** SENZA BORDO NEL DISPLAY **
- ** BUFFER CHUNKY. **
- ***********************************
- **** INPUT : **
- ** amb3d -> valore >0 ritornato **
- ** dalla funzione d'ini- **
- ** zializzazione. **
- ** buf -> puntatore ad array di **
- ** short int con coordi- **
- ** nate vertici. **
- ** col -> short int con colore **
- ** triangolo. **
- ** bordo-> =-1 senza bordo **
- ** >=0 colore bordo. **
- **** OUTPUT: **
- ** nessuno . **
- ***********************************/
- void drw_t(amb3d,buf,col,bordo)
- struct ambient3d *amb3d;
- short int *buf;
- long int col;
- long int bordo;
- {
- short int i;
- long int ii;
- short int xa,xb,ya,yb,y;
- struct pixl *vert;
- long int xm,ym,x;
- long int dy,dx1,dx2,dx3,xs,xe,ys,ys1,ys2;
- struct grafica *gf;
- unsigned char *tmp;
- #ifdef DEBUG
- char dbg[100];
- #endif
-
- vert=(struct pixl *)amb3d->temp;
- gf=amb3d->graf;
- xm=gf->clipdx;
- ym=gf->clipdy;
- tmp=(unsigned char *)gf->dbuf;
-
- vert[0].x=(long int)buf[0]<<PREC;
- vert[0].y=(long int)buf[1];
- vert[1].x=(long int)buf[2]<<PREC;
- vert[1].y=(long int)buf[3];
- vert[2].x=(long int)buf[4]<<PREC;
- vert[2].y=(long int)buf[5];
-
- /* riordino i vertici in base alla Y minore con bubble sort */
- if (vert[0].y > vert[1].y)
- {
- x=vert[0].x;
- y=vert[0].y;
- vert[0].x=vert[1].x;
- vert[0].y=vert[1].y;
- vert[1].x=x;
- vert[1].y=y;
- }
-
- if (vert[1].y > vert[2].y)
- {
- x=vert[1].x;
- y=vert[1].y;
- vert[1].x=vert[2].x;
- vert[1].y=vert[2].y;
- vert[2].x=x;
- vert[2].y=y;
- }
-
- if (vert[0].y > vert[1].y)
- {
- x=vert[0].x;
- y=vert[0].y;
- vert[0].x=vert[1].x;
- vert[0].y=vert[1].y;
- vert[1].x=x;
- vert[1].y=y;
- }
-
- /** calcolo spostamenti su asse x per tutti i segmenti del triangolo **/
- /** valori in fix point (x256) **/
- ys=vert[0].y;
- ys1=vert[1].y;
- ys2=vert[2].y;
-
- dy=ys1-ys;
- if (dy==NULL) dy=1;
- dx1=(vert[1].x-vert[0].x)/dy;
-
- dy=ys2-ys;
- if (dy==NULL) dy=1;
- dx2=(vert[2].x-vert[0].x)/dy;
-
- dy=ys2-ys1;
- if (dy==NULL) dy=1;
- dx3=(vert[2].x-vert[1].x)/dy;
-
- xs=vert[0].x;
- xe=xs;
-
- /** inizio tracciamenti **/
- ya=ys;
- yb=ys1;
-
- for(y=ya ; y<=yb ; y++)
- {
- xa=xs>>PREC;
- xb=xe>>PREC;
- ii=y*xm;
- if (y>=0 AND y<ym)
- {
- if (xa<xb)
- {
- for (i=xa ;i<=xb ;i++) if (i>=0 AND i<xm) tmp[ii+i]=col;
- }
- else
- {
- for (i=xb ;i<=xa ;i++) if (i>=0 AND i<xm) tmp[ii+i]=col;
- }
- }
- xs+=dx1;
- xe+=dx2;
- }
- /** traccio l'altra meta' del triangolo (se presente) **/
-
- xs=vert[2].x;
- xe=xs;
-
- ya=ys2;
- yb=ys1;
-
- for(y=ya ; y>=yb ; y--)
- {
- xa=xs>>PREC;
- xb=xe>>PREC;
- ii=y*xm;
- if (y>=0 AND y<ym)
- {
- if (xa<xb)
- {
- for (i=xa ;i<=xb ;i++) if (i>=0 AND i<xm) tmp[ii+i]=col;
- }
- else
- {
- for (i=xb ;i<=xa ;i++) if (i>=0 AND i<xm) tmp[ii+i]=col;
- }
- }
- xs-=dx2;
- xe-=dx3;
- }
- /* traccio eventuale bordo */
-
- if (bordo>=NULL)
- {
- line(amb3d,buf[0],buf[1],buf[2],buf[3],bordo);
- line(amb3d,buf[2],buf[3],buf[4],buf[5],bordo);
- line(amb3d,buf[4],buf[5],buf[0],buf[1],bordo);
- }
-
- }
-
- /***********************************
- ** DISEGNO UN QUADRILATERO CON O **
- ** SENZA BORDO NELLA RASTPORT **
- ** NASCOSTA. **
- ***********************************
- **** INPUT : **
- ** amb3d-> valore >0 ritornato **
- ** dalla funzione d'ini- **
- ** zializzazione. **
- ** buf -> puntatore ad array di **
- ** short int con coordi- **
- ** nate vertici. **
- ** col -> short int con colore **
- ** triangolo. **
- ** bordo-> =-1 senza bordo **
- ** >=0 colore bordo. **
- **** OUTPUT: **
- ** nessuno . **
- ***********************************/
- void drw_q(amb3d,buf,col,bordo)
- struct ambient3d *amb3d;
- short int *buf;
- long int col;
- long int bordo;
- {
- struct grafica *gf;
- short int buf1[6];
-
- gf=amb3d->graf;
- buf1[0]=buf[4];
- buf1[1]=buf[5];
- buf1[2]=buf[6];
- buf1[3]=buf[7];
- buf1[4]=buf[0];
- buf1[5]=buf[1];
-
- drw_t(amb3d,buf,col,-1);
- drw_t(amb3d,buf1,col,-1);
- /* traccio eventuale bordo */
-
- if (bordo>=NULL)
- {
- line(amb3d,buf[0],buf[1],buf[2],buf[3],bordo);
- line(amb3d,buf[2],buf[3],buf[4],buf[5],bordo);
- line(amb3d,buf[4],buf[5],buf[6],buf[7],bordo);
- line(amb3d,buf[6],buf[7],buf[0],buf[1],bordo);
- }
-
- }
-
-